#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#
# Copyright 2017 Intel Corporation All Rights Reserved.
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

import SCons
import os
import platform
import subprocess
from distutils.version import StrictVersion
Import('env')

PROJECT_VERSION = env.get('PROJECT_VERSION')

TARGET_ARCH = env.get('TARGET_ARCH')
if env.get('RELEASE'):
    RELEASE = "release"
else:
    RELEASE = "debug"
SECURED = env.get('SECURED')

target_os = env.get('TARGET_OS')

if env.get('WITH_CLOUD'):
    CLOUD = 1
else:
    CLOUD = 0

if env.get('WITH_TCP'):
    TCP = 1
else:
    TCP = 0
if env.get('MULTIPLE_OWNER'):
    ANDROID_MULTIPLE_OWNER = 1
else:
    ANDROID_MULTIPLE_OWNER = 0

MQ = env.get('WITH_MQ')
MQ_SUB = 0
MQ_PUB = 0
MQ_BROKER = 0
RD_MODE = env.get('RD_MODE')
TARGET_TRANSPORT = env.get('TARGET_TRANSPORT')
TRANSPORT_EDR = 0
TRANSPORT_BLE = 0
TRANSPORT_NFC = 0

if 'SUB' in MQ:
    MQ_SUB = 1
if 'PUB' in MQ:
    MQ_PUB = 1
if 'BROKER' in MQ:
    MQ_BROKER = 1

if 'ALL' in TARGET_TRANSPORT:
    TRANSPORT_EDR = 1
    TRANSPORT_BLE = 1
    TRANSPORT_NFC = 1
    print("Android Transport is ALL")
else:
    if 'BT' in TARGET_TRANSPORT:
        TRANSPORT_EDR = 1
    if 'BLE' in TARGET_TRANSPORT:
        TRANSPORT_BLE = 1
    if 'NFC' in TARGET_TRANSPORT:
        TRANSPORT_NFC = 1

if target_os in ['android']:
    android_home = env.get('ANDROID_HOME')
    os.environ['ANDROID_HOME'] = env.get('ANDROID_HOME')
    os.environ['ANDROID_NDK_HOME'] = env.get('ANDROID_NDK')
    if not os.path.exists(android_home + '/platforms/android-21') or \
       not os.path.exists(android_home + '/build-tools/20.0.0'):
        print(
'''
***************************************** Info ********************************
*   Either 'Android API 21' is not installed or 'Android SDK Build Tools      *
*   20.0.0' is not installed. The Android SDK Manager will now open. Please   *
*   be sure to deselect all options, then select the following 2 packages:    *
*       1. Under "Tools" select "Android SDK Build-tools" Revision 20.        *
*       2. Under "Android 5.0.1 (API 21)" select "SDK Platform"               *
*       3. Continue by selecting "Install 2 Packages"                         *
*                                                                             *
*   NOTE: If you have an http proxy, please press ctrl+c now and edit/create  *
*         the following file in your $HOME directory as follows:              *
*                                                                             *
* Edit/Create file: "$HOME/.android/androidtool.cfg"                          *
*                                                                             *
*    http.proxyPort=<YOUR_PORT_NUMBER>                                        *
*    sdkman.monitor.density=108                                               *
*    http.proxyHost=<YOUR_HTTP_PROXY_ADDRESS>                                 *
*    sdkman.show.update.only=true                                             *
*    sdkman.ask.adb.restart=false                                             *
*    sdkman.force.http=true                                                   *
*    sdkman.show.updateonly=true                                              *
*                                                                             *
*******************************************************************************

...Opening Android SDK Manager now. Once you are finished, the build will continue.
''')
        os.system(android_home + '/tools/android')


def ensure_libs(target, source, env):
    if platform.system() == 'Windows':
        return target, [source, env.get('BUILD_DIR') + 'ca-interface.dll',
                                env.get('BUILD_DIR') + 'ocstack-jni.dll']
    else:
        return target, [source, env.get('BUILD_DIR') + 'libca-interface.so',
                                env.get('BUILD_DIR') + 'liboc.so',
                                env.get('BUILD_DIR') + 'liboc_logger.so',
                                env.get('BUILD_DIR') + 'libocstack-jni.so']

def find_scons_java_version(env):
    '''
    Attempt to find the version of the javac tool that will be used to build
    the java code.
    This will return a string that SHOULD be placed into SCons' JAVAVERSION
    environment variable.
    If a version can not be determined return None
    '''
    possible_versions = ['1.8', '1.7', '1.6', '1.5']
    # This command is used to get the java version used.
    # Then walk through the output line by line to see if it has one of the
    # expected java version. Note older versions of SCons do not support newer
    # versions of Java. Since the way java code is compiled by SCons has not
    # changed significantly since Java 1.6 we just tell SCons to use the
    # maximum version of Java that was supported for by SCons for a given
    # release
    # SCons 2.1.0 Java 1.6 support (older versions of SCons were not investigated)
    # SCons 2.3.0 Java 1.7 support added
    # SCons 2.3.3 Java 1.8 support added
    # Versions were renamed again, the successor releases are 9 and 10
    # at scons 3.0, 1.8 is still the max version supported in scons,
    # so use 1.8 (or the max for executing scons) for the JAVAVERSION for these.
    print('Trying to discover the version of Java used for compilation')
    javac_cmd = os.path.join(env['JAVA_HOME'], 'bin', 'javac')
    try:
        java_ver = subprocess.check_output([javac_cmd, '-version'], stderr=subprocess.STDOUT)
    except OSError:
        msg = "Error: could not find Java compiler at %s, unable to proceed" % javac_cmd
        Exit(msg)
    scons_version =  SCons.__version__
    if StrictVersion(scons_version) < StrictVersion('2.1.0'):
        print('\t***** Version of SCons older than 2.0.0 detected.                     *****')
        print('\t***** Java build will likely fail or have errors in the build output. *****')
        print('\t***** Recommend updating to the latest version of SCons               *****')
        return None
    for line in SCons.Util.to_String(java_ver).split('\n'):
        # handle building with versions of Java not supported by SCons
        if ' 10' in line:
            print('\tJava version 10 found.')
            if StrictVersion(scons_version) <= StrictVersion('2.2.0'):
                print(('\tJava 10 not supported in SCons ' + scons_version + ', max supported Java 1.6.'))
                print('\tSetting JAVAVERSION to 1.6')
                return '1.6'
            if StrictVersion(scons_version) <= StrictVersion('2.3.2'):
                print(('\tJava 10 not supported in SCons ' + scons_version + ', max supported Java 1.7.'))
                print('\tSetting JAVAVERSION to 1.7')
                return '1.7'
            if StrictVersion(scons_version) > StrictVersion('3.0.1'):
                # only printing this if Java 10 is found. Newer versions of
                # scons should be able to handle older versions of Java
                print('\t***** Unrecognized version of SCons found in java version check. Build script may need to be updated *****')
                # drop through to the next if statement.
            if StrictVersion(scons_version) > StrictVersion('2.3.2'):
                print(('\tJava 10 not supported in SCons ' + scons_version + ', max supported Java 1.8.'))
                print('\tSetting JAVAVERSION to 1.8')
                return '1.8'
        if ' 9' in line:
            print('\tJava version 9 found.')
            if StrictVersion(scons_version) <= StrictVersion('2.2.0'):
                print(('\tJava 9 not supported in SCons ' + scons_version + ', max supported Java 1.6.'))
                print('\tSetting JAVAVERSION to 1.6')
                return '1.6'
            if StrictVersion(scons_version) <= StrictVersion('2.3.2'):
                print(('\tJava 9 not supported in SCons ' + scons_version + ', max supported Java 1.7.'))
                print('\tSetting JAVAVERSION to 1.7')
                return '1.7'
            if StrictVersion(scons_version) > StrictVersion('3.0.1'):
                # only printing this if Java 9 is found. Newer versions of
                # scons should be able to handle older versions of Java
                print('\t***** Unrecognized version of SCons found in java version check. Build script may need to be updated *****')
                # drop through to the next if statement.
            if StrictVersion(scons_version) > StrictVersion('2.3.2'):
                print(('\tJava 9 not supported in SCons ' + scons_version + ', max supported Java 1.8.'))
                print('\tSetting JAVAVERSION to 1.8')
                return '1.8'
        if ' 1.8' in line:
            print('\tJava version 1.8 found.')
            if StrictVersion(scons_version) <= StrictVersion('2.2.0'):
                print(('\tJava 1.8 not supported in SCons ' + scons_version + ', max supported Java 1.6.'))
                print('\tSetting JAVAVERSION to 1.6')
                return '1.6'
            if StrictVersion(scons_version) <= StrictVersion('2.3.2'):
                print(('\tJava 1.8 not supported in SCons ' + scons_version + ', max supported Java 1.7.'))
                print('\tSetting JAVAVERSION to 1.7')
                return '1.7'
        if ' 1.7' in line:
            print('\tJava version 1.7 found.')
            if StrictVersion(scons_version) <= StrictVersion('2.2.0'):
                print(('\tJava 1.7 not supported in SCons ' + scons_version + ', max supported Java 1.6.'))
                print('\tSetting JAVAVERSION to 1.6')
                return '1.6'
        # handle versions supported by SCons
        for v in possible_versions:
            if (' ' + v) in line:
                print(('\tSetting JAVAVERSION to ' + v))
                return v
    print('\tJava version NOT found!')
    return None

jniOut = SConscript('jni/SConscript')

target_variant = "java"
if target_os == 'android':
    target_variant = "android"

jdk_env = None
if target_os in ['android']:
    # Gradle needs some settings in the environment:
    jdk_env = env.Clone(ENV={'JAVA_HOME':env['JAVA_HOME'],
                             'ANDROID_HOME':env['ANDROID_HOME'],
                             'TERM':env['ENV']['TERM']})
else:
    jdk_env = env.Clone()

cmdBuildApi = []
cmdBuildExamples = []
if target_os in ['android']:
    jdk_env['BUILDERS']['Gradle'] = Builder(
        action=env.get('ANDROID_GRADLE') + ' build -b ' + env.get('SRC_DIR') +
        '/java/iotivity-%s/build.gradle -PPROJECT_VERSION=%s -PWITH_TRANSPORT_EDR=%s -PWITH_TRANSPORT_BLE=%s -PWITH_TRANSPORT_NFC=%s -PTARGET_ARCH=%s -PRELEASE=%s -PSECURED=%s -DSECURE=%s -PWITH_CLOUD=%s -PRD_MODE=%s -PWITH_MQ_PUB=%s -PWITH_MQ_SUB=%s -PWITH_MQ_BROKER=%s -PWITH_TCP=%s -PMULTIPLE_OWNER=%s -PBUILD_DIR=%s --stacktrace'
        % (target_variant, PROJECT_VERSION, TRANSPORT_EDR, TRANSPORT_BLE, TRANSPORT_NFC,
           TARGET_ARCH, RELEASE, SECURED, SECURED, CLOUD, RD_MODE, MQ_PUB, MQ_SUB,
           MQ_BROKER, TCP, ANDROID_MULTIPLE_OWNER, env.get('BUILD_DIR')),
        emitter=ensure_libs)
    jdk_env['BUILD_DIR'] = env.get('BUILD_DIR')

    cmdBuildApi = jdk_env.Gradle(
        target="base/objs",
        source="common/src/main/java/org/iotivity/base/OcResource.java")

    jdk_env.NoClean(cmdBuildApi)
    jdk_env['BUILDERS']['Gradle'] = Builder(
        action=env.get('ANDROID_GRADLE') + ' build -b ' +
        'java/examples-%s/build.gradle -PPROJECT_VERSION=%s -DWITH_TRANSPORT_EDR=%s -DWITH_TRANSPORT_BLE=%s -DWITH_TRANSPORT_NFC=%s -PTARGET_OS=%s -PTARGET_ARCH=%s -PRELEASE=%s -PSECURED=%s -DSECURE=%s -PWITH_CLOUD=%s -PRD_MODE=%s -PWITH_MQ_PUB=%s -PWITH_MQ_SUB=%s -PWITH_MQ_BROKER=%s -PWITH_TCP=%s -PMULTIPLE_OWNER=%s -PBUILD_DIR=%s --stacktrace'
        % (target_variant, PROJECT_VERSION, TRANSPORT_EDR, TRANSPORT_BLE,
           TRANSPORT_NFC, target_os, TARGET_ARCH, RELEASE, SECURED, SECURED, CLOUD,
           RD_MODE, MQ_PUB, MQ_SUB, MQ_BROKER, TCP, ANDROID_MULTIPLE_OWNER,
           env.get('BUILD_DIR')))
    #cmdBuildExamples=jdk_env.Gradle(target="../examples-%s/devicediscoveryclient/apk" % (target_variant, ), source="examples-%s/devicediscoveryclient/src/main/java/org/iotivity/base/examples/DeviceDiscoveryClient.java" % (target_variant, ))
    cmdBuildExamples = jdk_env.Gradle(
        target="examples-%s/simpleclient/jar" % (target_variant, ),
        source=
        "examples-%s/simpleclient/src/main/java/org/iotivity/base/examples/SimpleClient.java"
        % (target_variant, ))
    jdk_env.NoClean(cmdBuildExamples)

    if target_os != 'android':
        exampleAclFiles = jdk_env.Install(
            '.',
            'examples-java/simpleserver/src/main/assets/oic_svr_db_server.dat')
        exampleAclFiles += jdk_env.Install(
            '.',
            'examples-java/simpleserver/src/main/assets/oic_svr_db_server.dat')
        Depends(exampleAclFiles, cmdBuildExamples)

    Depends(cmdBuildExamples, cmdBuildApi)
    Depends(cmdBuildExamples, jniOut)
else:
    # Build iotivity.jar
    # TODO At this time we expect this build flag is required for i18n support
    # need to do additional testing to verify this assumption.
    jdk_env.Append(JAVACFLAGS=['-encoding', 'UTF-8'])
    java_v =  find_scons_java_version(jdk_env)
    if java_v != None:
        jdk_env.Append(JAVAVERSION=java_v)
    jdk_env.Append(JAVASOURCEPATH=['java/iotivity-java/src/main/java', 'java/common/src/main/java'])
    java_class_out = jdk_env.Java(target='classes', source=['iotivity-java/src/main/java', 'common/src/main/java'])
    cmdBuildApi = jdk_env.Jar(target='iotivity.jar', source=java_class_out)

    # Build examples
    jdk_env.SConscript('examples-java/SConscript', exports='jdk_env')

if target_os == 'android':
    jdk_env.Clean(cmdBuildExamples, '#/java/iotivity-android/build/')
    jdk_env.Clean(cmdBuildExamples, '#/java/examples-android/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/cloudprovisioningclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/devicediscoveryclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/devicediscoveryserver/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/fridgeclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/fridgegroupclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/fridgegroupserver/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/fridgeserver/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/groupclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/groupserver/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/presenceclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/presenceserver/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/provisioningclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/simplebase/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/simpleclient/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/simpleserver/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/simpleclientserver/build/')
    jdk_env.Clean(cmdBuildExamples,
                  '#/java/examples-android/simpleserver/build/')

env.AppendUnique(baseAAR=cmdBuildApi)
